<?php

namespace App\Service\VendorClient\Shopsanshisanke;

use App\Service\Code\Normal;
use App\Service\BaseService;
use App\Model\PssModel\ServiceConfig;
use Service\AppService\IdService;
use App\Service\TaskServer\TaskWorker;
use Hyperf\Utils\WaitGroup;

/**
 * 叁拾叁刻上游对接
 * @author: hj
 */
class ShopsanshisankeApiClient extends BaseService {
    //供应商编号
    const SUPPLIER_CODE = 'shopsanshisanke';

    //配置文件
    private $config = [];
    //商品类型（0-一般贸易，1-保税，2-海外直邮）
    public static $goodsType = [
        '000'  => '0',
        '1210' => '1',
        '9610' => '2',
        '9810' => '2',
    ];

    public function __construct($apiBody = []) {
        $this->config = $apiBody;
    }

    /**
     * 创建订单
     */
    public function createOrder($param = []) {
        if (empty($param['supplierOrder']) || empty($param['orderGoods']) || empty($param['order']) || empty($param['binfo'])) {
            return Normal::returnCode(Normal::FAIL, "except param supplierOrder or orderGoods or order or binfo");
        }
        $orderInfo = $param['supplierOrder'];
        $goodsList = $param['orderGoods'];
        $order     = $param['order'];
        $binfo     = $param['binfo'];
        $order_sn  = $orderInfo['supplier_dsn'];
        //订单时间
        $order_time = $orderInfo['cd'] ? date('Y-m-d H:i:s', $orderInfo['cd']) : date('Y-m-d H:i:s', time());
        //支付时间
        $pay_time = isset($order['payTime']) && !empty($order['payTime']) ? date('Y-m-d H:i:s', $order['payTime']) : date('Y-m-d H:i:s', time());
        //运费分摊
        $deliver_money = $orderInfo['deliver_money'];
        //优惠
        $discount_money = $orderInfo['discount_money'];
        //下单支付的时候支付信息
        $apply_extends = @json_decode($orderInfo['apply_extends'], true);
        //用户实际支付金额
        $real_total_money = $orderInfo['real_total_money'];
        //支付公司和电商平台
        $payCommanyCode = isset($apply_extends['payCommanyCode']) && !empty($apply_extends['payCommanyCode']) ? $apply_extends['payCommanyCode'] : '';
        $payCommanyCode = isset($order['payCommanyCode']) && !empty($order['payCommanyCode']) ? $order['payCommanyCode'] : $payCommanyCode;
        $payCommanyName = isset($apply_extends['payCommanyName']) && !empty($apply_extends['payCommanyName']) ? $apply_extends['payCommanyName'] : '';
        $payCommanyName = isset($order['payCommanyName']) && !empty($order['payCommanyName']) ? $order['payCommanyName'] : $payCommanyName;
        try {
            $payWay = ServiceConfig::instance()->getConfigByEventsValue(self::SUPPLIER_CODE, ServiceConfig::TYPE_PAY, $payCommanyCode);
        } catch (\Throwable $th) {
            return Normal::returnCode(Normal::FAIL, "支付方式获取异常：【{$th->getMessage()}】");
        }
        if (empty($payWay)) {
            return Normal::returnCode(Normal::FAIL, "支付公司：【{$payCommanyName}】未映射，请联系管理员处理");
        }
        $paySerial      = isset($apply_extends['paySerial']) && !empty($apply_extends['paySerial']) ? $apply_extends['paySerial'] : '';
        $paySerial      = isset($order['paySerial']) && !empty($order['paySerial']) ? $order['paySerial'] : $paySerial;
        $enterpriseNum  = isset($apply_extends['enterpriseNum']) && !empty($apply_extends['enterpriseNum']) ? $apply_extends['enterpriseNum'] : '';
        $enterpriseNum  = isset($order['enterpriseNum']) && !empty($order['enterpriseNum']) ? $order['enterpriseNum'] : $enterpriseNum;
        $enterpriseName = isset($apply_extends['enterpriseName']) && !empty($apply_extends['enterpriseName']) ? $apply_extends['enterpriseName'] : '';
        $enterpriseName = isset($order['enterpriseName']) && !empty($order['enterpriseName']) ? $order['enterpriseName'] : $enterpriseName;

        //商品总金额
        //获取下单商品信息
        $palceOrderGoods    = [];
        $totalGoodsMoney    = '0.00';
        $goodsTotalMoney    = '0.00';
        $goodsTotalMoneyNot = '0.00';
        $wayTaxFee          = '0.00';
        foreach ($goodsList as $key => $item) {
            $tax_rate         = bcadd('1', (string)$item['tax_rate'], 4);
            $price            = $item['price'];
            $spec_num         = $item['spec_num'];
            $quantity         = $item['quantity'];
            $supplier_skucode = $item['supplier_skucode'];
            $goods_type       = $item['goods_type'];
            //实际购买数量(下单数量 X 起售数量)
            $buyAcount = $spec_num * $quantity;
            // if ($key == 0) {
            //     $singleDeliveryMoney = bcdiv((string)$deliver_money, (string)$quantity, 3);
            //     $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney, (string)100, 1);
            //     $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100, 2);
            //     $price               = bcadd((string)$price, (string)$singleDeliveryMoney, 2);
            // }
            //不含税价格
            $singleGoodsPrice = bcdiv((string)$price, $tax_rate, 3);
            $singleGoodsPrice = bcmul((string)$singleGoodsPrice, (string)100, 1);
            $singleGoodsPrice = bcdiv((string)ceil($singleGoodsPrice), (string)100, 2);
            //商品不含税总价
            $goodsTotalPrice = bcmul((string)$singleGoodsPrice, (string)$quantity, 2);
            //含税总价
            $goodsTotalPriceTax = bcmul((string)$price, (string)$quantity, 2);
            //税费
            $tax    = bcsub((string)$price, (string)$singleGoodsPrice, 2);
            $taxAll = bcmul($tax, (string)$quantity, 2);
            //判断是不是保税订单
            $taxAll = $goods_type == 1 ? $taxAll : 0;
            //不含税总金额
            $goodsTotalMoneyNot = bcadd((string)$goodsTotalMoneyNot, $goodsTotalPrice, 2);
            //含税总金额
            $goodsTotalMoney = bcadd((string)$goodsTotalMoney, $goodsTotalPriceTax, 2);
            //总税费
            $wayTaxFee = bcadd((string)$wayTaxFee, (string)$taxAll, 2);
            //下单商品组
            $goodsInfo         = [
                "goodssn"   => trim($item['supplier_skucode']),//如实填写
                "goodsType" => "1",//固定值
                "hasoption" => "0",//固定值
                "total"     => $quantity,//如实填写
                "title"     => trim($item['goods_name']),//如实填写
                "price"     => $price,        //如实填写 税后价
                "realprice" => $price,//如实填写 实际支付价格
                "productsn" => trim($item['supplier_skucode'])//如实填写，没有可填写商品编码（goodssn）
            ];
            $palceOrderGoods[] = $goodsInfo;
        }
        $totalMoney = bcadd($goodsTotalMoney, (string)$deliver_money, 2);
        //用户实际支付金额
        $real_total_money = $orderInfo['real_total_money'];
        //订单优惠金额
        $discount_money = bcsub($totalMoney, (string)$real_total_money, 2);
        $tradeData      = [
            "ordersn"          => $order_sn,//订单号
            "orderid"          => 123,//订单号
            "openid"           => 123,//订单号
            "type"             => "0",//固定值
            "platformName"     => $this->config["platformName"] ?? '',//平台名称
            "plattime"         => strtotime($order_time),//如实填写 订单创建时间
            "warehousecode"    => "rizhao",//固定值 仓库代码
            "express_code"     => '',//有就填写，没有就空着
            "expresssn"        => '',//有就填写，没有就空着
            "ordertype"        => "I",//固定值 订单进出口标识	I 进口 O出口
            "tradeMode"        => "1210",//固定值 贸易方式
            "price"            => $goodsTotalMoney,//如实填写  订单金额 所有商品的单价乘数量的和
            "goodsprice"       => $goodsTotalMoney,//如实填写 商品金额
            "totalbeforetaxes" => $goodsTotalMoneyNot,//如实填写  总税前价
            "totaltaxes"       => $wayTaxFee,//如实填写 总税金
            "couponprice"      => "0.00",//如实填写 优惠券金额
            "discountprice"    => $discount_money,//如实填写  折扣价格
            "dispatchprice"    => $deliver_money,//如实填写  运费
            "realprice"        => $real_total_money,//实际支付金额
            "hgpayid"          => $paySerial,//支付单号
            "paytime"          => strtotime($pay_time),//如实填写 支付时间
            "paytype"          => $payWay,//支付方式代码 支付方式 	21：微信 22：支付宝
            "buyername"        => $orderInfo["buyer_realname"],//如实填写 购买人名称
            "buyercardid"      => $orderInfo["buyer_idcard"],//如实填写 购买人身份证
            "merchid"          => $this->config['merchid']//固定值 综服入驻企业id
        ];
        $goods          = $palceOrderGoods;
        $logistics      = [
            "realname" => $orderInfo['receive_name'],
            "mobile"   => $orderInfo['recveive_phone'],
            "province" => $orderInfo['province'],
            "city"     => $orderInfo['city'],
            "area"     => $orderInfo['district'],
            "address"  => $orderInfo['receive_address']
        ];
        $data           = [
            'method' => 'createOrder',
            'data'   => $this->arrToXml($tradeData, $goods, $logistics),
        ];
        return $this->orderExe($data);
    }

    /**
     * 商品列表查询
     * @param $data
     * @return array
     */
    public function queryGoodsList($param = []) {
        $page  = $param['page'] ?? 1;
        $limit = $param['limit'] ?? 20;
        $data  = [
            'method' => 'goodsList',
            'data'   => [
                'page_no'   => $page,//页数
                'page_size' => $limit,//每页条数
            ],
        ];
        $res1  = $this->goodsExe($data);
        if ($res1['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, "当前商品列表数据获取异常【{$res1['msg']}】");
        }
        if (!isset($res1['data']['data']) || empty($res1['data']['data'])) {
            return Normal::returnCode(Normal::SUC, '获取完成', ['total' => 0, 'data' => []]);
        }
        $itemList     = $res1['data']['data'];
        $itemInfoList = [];
        $count        = count($itemList);
        $wg           = new WaitGroup();
        $wg->add($count);
        foreach ($itemList as $item) {
            co(function () use ($wg, $item, &$itemInfoList) {
                //详情
                $queryGoodsDetailRes = $this->queryGoodsDetail($item['item_id']);
                if ($queryGoodsDetailRes['code'] == Normal::SUC) {
                    if ($queryGoodsDetailRes['data']) {
                        $itemInfoList[] = $queryGoodsDetailRes['data'];
                    }
                }
                $wg->done();
            });
        }
        $wg->wait();
        $itemInfoListById = array_column($itemInfoList, null, 'item_id');
        if (empty($itemInfoListById)) {
            return Normal::returnCode(Normal::SUC, '获取完成', ['total' => 0, 'data' => []]);
        }
        $newData = [];
        foreach ($itemInfoListById as $itemId => $itemInfo) {
            if (!isset($itemInfo['sku']) || empty($itemInfo['sku'])) {
                continue;
            }
            foreach ($itemInfo['sku'] as $skuId => $sku) {
                $newData[] = [
                    'item_id'          => $sku['item_id'],
                    'sku_id'           => $sku['sku_id'],
                    'barcode'          => $sku['barcode'],
                    'price'            => $sku['price'],
                    'mkt_price'        => $sku['mkt_price'],
                    'goodsbn'          => $sku['goodsbn'],
                    'img_list'         => $sku['image_list'],
                    'main_img'         => $sku['image_default_id'],
                    'realStore'        => $sku['realStore'],
                    'goods_name'       => $sku['title'],
                    'sub_title'        => $itemInfo['sub_title'],
                    'wap_desc'         => $itemInfo['wap_desc'],
                    'cat_name'         => $itemInfo['cat_name'],
                    'brand_name'       => $itemInfo['brand_name'],
                    'country_name'     => $itemInfo['country_name'],
                    'weight'           => $sku['weight'] ? bcmul((string)($sku['weight']), '1000', 4) : '0.0000',//kg 转化为g
                    'unit'             => $itemInfo['unit'],
                    "item_model"       => self::$goodsType[$itemInfo['item_model']] ?? '0', //商品贸易类型 '0000' =>('一般贸易'), '1210' =>('跨境保税'), '9610' =>('跨境直邮'), '9810' =>('个人直邮'),
                    "is_free_shipping" => 0,//是否包邮 1是 0否 商品不包邮 都是满59免运费
                    "approve_status"   => $itemInfo['approve_status'] == 'onsale' ? 1 : '0',//商品在售状态/onsale在售/instock下架
                    'rate_num'         => $itemInfo['rate_num'] ?? 0,//税率
                    'batchId'          => $sku['batchId'],//账册号  批次/效期
                    'single_min_limit' => $sku['single_min_limit'],//单次起购数量  0 不设限
                    'single_max_limit' => $sku['single_max_limit'],//单次起购数量 0不设限
                    'depotId'          => $sku['depotId'] ?? '',//仓库ID
                ];
            }
        }
        if (empty($newData)) {
            return Normal::returnCode(Normal::SUC, '获取完成', ['total' => 0, 'data' => []]);
        }
        return Normal::returnCode(Normal::SUC, '获取成功', ['total' => count($newData), 'data' => $newData]);
    }

    /**
     * 商品详情查询
     * @param $item_id
     * @return array
     */
    public function queryGoodsDetail($item_id) {
        $data = [
            'method' => 'goodsDetail',
            'data'   => [
                'item_id'   => $item_id,//item_id
                "region_id" => $this->config['regionId'] ?? "山东省/临沂市/兰山区",//山东省/临沂市/兰山区
            ],
        ];
        $res  = $this->goodsExe($data);
        if ($res['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, "当前商品详情数据获取异常【{$res['msg']}】");
        }
        if (!isset($res['data']['data']) || empty($res['data']['data'])) {
            return Normal::returnCode(Normal::SUC, '获取完成', []);
        }
        if (!isset($res['data']['data']['item']) || empty($res['data']['data']['item'])) {
            return Normal::returnCode(Normal::SUC, '获取完成', []);
        }
        return Normal::returnCode(Normal::SUC, '获取完成', $res['data']['data']['item']);
    }

    /**
     * 商品CURL请求
     * @param $param
     * @return array
     */
    public function goodsExe($param = []) {
        if (!isset($this->config[$param['method']])) {
            return Normal::returnCode(Normal::FAIL, "商品相关请求路由未设置【{$param['method']}】");
        }
        if (empty($param['data'])) {
            return Normal::returnCode(Normal::FAIL, "商品相关请求数据不能为空【{$param['method']}】");
        }
        $url = $this->config['goodsBaseUrl'];
        if (empty($url)) {
            return Normal::returnCode(Normal::FAIL, "商品相关接口请求地址不能为空");
        }
        $pushData           = $param['data'];
        $pushData['method'] = $this->config[$param['method']];
        $pushData['v']      = $this->config['v'];
        $parameter          = [
            [
                'tag'    => self::SUPPLIER_CODE . '_' . $param['method'],
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $url,
                'data'   => $pushData,
                'method' => 'post',
                'format' => 'json',
                'header' => [
                    'Content-type:application/json'
                ],
            ],
        ];
        $resTask            = TaskWorker::instance()->addTask($parameter, 'handleDiableTask');
        $resTask            = current($resTask);
        $result             = @json_decode($resTask['response']['result'], true);
        if (isset($result['errorcode']) && $result['errorcode'] == 0) {
            return Normal::returnCode(Normal::SUC, "商品相关请求成功", $result);
        }
        $msg = $result['msg'] ?? '商品相关请求结果失败';
        return Normal::returnCode(Normal::FAIL, $msg, $result);
    }

    /**
     * 订单CURL请求
     * @param $param
     * @return array
     */
    public function orderExe($param = []) {
        if (!isset($this->config[$param['method']])) {
            return Normal::returnCode(Normal::FAIL, "订单相关请求路由未设置【{$param['method']}】");
        }
        if (empty($param['data'])) {
            return Normal::returnCode(Normal::FAIL, "订单相关请求数据不能为空【{$param['method']}】");
        }
        $url = $this->config[$param['method']];
        if (empty($url)) {
            return Normal::returnCode(Normal::FAIL, "订单相关接口地址不能为空【{$param['method']}】");
        }
        $pushData  = [
            'xmlstr'  => base64_encode($param['data']),
            'keystr'  => base64_encode($this->config['keystr']),
            'merchid' => $this->config['merchid'],
        ];
        $parameter = [
            [
                'tag'    => self::SUPPLIER_CODE . '_' . $param['method'],
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $url,
                'data'   => $pushData,
                'method' => 'post',
                'format' => 'json',
                'header' => [
                    'Content-type:application/json',
                    "Access-Token:{$this->config['accessToken']}"
                ],
            ],
        ];
        $resTask   = TaskWorker::instance()->addTask($parameter);
        $resTask   = current($resTask);
        // $result    = @json_decode($resTask['response']['result'], true);
        $result = $this->xmlToArr($resTask['response']['result']);
        if (!isset($result['return']) || empty($result['return'])) {
            return Normal::returnCode(Normal::FAIL, '请求失败', $result);
        }
        $return = $result['return'];
        if (isset($return['Result']) && $return['Result'] == 1) {
            return Normal::returnCode(Normal::SUC, "订单相关请求成功", $result);
        } else {
            $msg = $return['ResultMsg'] ?? '订单相关请求结果失败';
            return Normal::returnCode(Normal::FAIL, $msg, $result);
        }
    }

    /**
     * 组装xml
     */
    public function arrToXml($tradeData, $Goods, $Logistics) {
        $xmlstr = '<?xml version="1.0" encoding="UTF-8"?><XMLInfo><Order>';
        foreach ($tradeData as $k => $v) {
            $xmlstr .= sprintf('<%s>%s</%s>', $k, $v, $k);
        }
        $xmlstr .= '<Goods>';

        foreach ($Goods as $ke => $ve) {
            $xmlstr .= '<Detail>';
            foreach ($ve as $ket => $vat) {
                $xmlstr .= sprintf('<%s>%s</%s>', $ket, $vat, $ket);
            }
            $xmlstr .= '</Detail>';
        }

        $xmlstr .= '</Goods><Logistics>';
        foreach ($Logistics as $k => $v) {
            $xmlstr .= sprintf('<%s>%s</%s>', $k, $v, $k);
        }
        $xmlstr .= '</Logistics></Order></XMLInfo>';
        return $xmlstr;
    }

    /**
     * 转换array
     */
    public function xmlToArr($xml_string = '') {
        $xml = simplexml_load_string($xml_string);
        return json_decode(json_encode($xml), true);
    }
}